package no.sachmuld.methodcombination.examples.adapter.designbycontract;

import no.sachmuld.methodcombination.api.Condition;
import no.sachmuld.methodcombination.api.MethodInvocation;
import no.sachmuld.methodcombination.api.BehaviourChain;
import no.sachmuld.methodcombination.api.adapter.DesignByContract;

import java.lang.*;

/**
 *
 */
public class Courier {

    private BehaviourChain<CourierBehaviour> chain = new BehaviourChain<>();

    protected Courier with(CourierBehaviour... behaviours) {
        chain.addAll(behaviours);
        return this;
    }

    public Courier() {

        with(new CourierBehaviour() {

            @Override
            public Condition beforeDeliver(Package pkg) {
                return new Condition("package weight < 3", pkg.getWeightInKg() < 3);
            }

            @Override
            public Delivery deliver(Package pkg, MethodInvocation<Delivery> methodInvocation) {
                return new Delivery(6);
            }

            @Override
            public Condition afterDeliver(Delivery delivery) {
                return new Condition("delivery time < 8", delivery.getDeliveryTimeInHours() < 8);
            }

        });
    }

    public final Delivery deliver(final Package pkg) {
        return new DesignByContract<CourierBehaviour, Delivery>(chain) {

            @Override
            protected Condition executePrecondition(CourierBehaviour behaviour) {
                return behaviour.beforeDeliver(pkg);
            }

            @Override
            protected Delivery executePrimary(CourierBehaviour behaviour, MethodInvocation<Delivery> methodInvocation) {
                return behaviour.deliver(pkg, methodInvocation);
            }

            @Override
            protected Condition executePostcondition(CourierBehaviour behaviour, Delivery delivery) {
                return behaviour.afterDeliver(delivery);
            }
        }.execute();
    }
}
